// 主体信息表
import { compact } from 'lodash';
import dayjs from 'dayjs';
import { DataTypes, UUIDV4 } from 'sequelize';
import { MySqlModel, getSequelize } from '../db';
import { stars, starMap } from '../values';
import { getToday } from '../utils';

/**
 * 日志记录字段
 * logger: 是否记录日志
 * map: key value类型映射对象
 * model: 外键关联表 例如 Users
 * column: 外键值列名 例如 login_name
 */
class Hotels extends MySqlModel {
  static async checkLicense(hotelId) {
    const hotel = await Hotels.findOne({ where: { id: hotelId }, rejectOnEmpty: new Error('Hotel not found') });

    const today = getToday();
    if (!(today >= hotel.begin_date && today <= hotel.end_date)) {
      throw new Error(`订阅有效期为${hotel.begin_date} ~ ${hotel.end_date}`);
    }
  }
}

Hotels.init({
  id: {
    type: DataTypes.UUID, unique: 'id', allowNull: false, defaultValue: UUIDV4, validate: { isUUID: 4 }, primaryKey: true, comment: '主键'
  },
  code: {
    type: DataTypes.STRING(50), unique: 'code', allowNull: false, comment: '主体代码', editable: false
  },
  name: {
    type: DataTypes.STRING(200), allowNull: false, comment: '主体名称'
  },
  begin_date: {
    type: DataTypes.DATEONLY, allowNull: false, comment: '开始日期'
  },
  end_date: {
    type: DataTypes.DATEONLY, allowNull: false, comment: '结束日期'
  },
  state_id: {
    type: DataTypes.UUID, allowNull: true, defaultValue: null, comment: '省份'
  },
  city: {
    type: DataTypes.STRING(50), allowNull: true, defaultValue: null, comment: '城市'
  },
  address: {
    type: DataTypes.STRING(100), allowNull: true, defaultValue: null, comment: '地址'
  },
  group: {
    type: DataTypes.STRING(50), allowNull: true, defaultValue: null, comment: '集团'
  },
  owner: {
    type: DataTypes.STRING(50), allowNull: true, defaultValue: null, comment: '业主'
  },
  star: {
    type: DataTypes.STRING(10), allowNull: true, defaultValue: null, comment: '星级', map: starMap
  },
  rooms: {
    type: DataTypes.INTEGER,
    allowNull: true,
    defaultValue: null,
    validate: {
      isValidate(value) {
        if (parseInt(value, 10) < 0) {
          throw new Error('房间数不能是负数');
        }
      }
    },
    comment: '房间数',
    logger: true
  },
  contact_name: {
    type: DataTypes.STRING(50), allowNull: true, defaultValue: null, comment: '联系人'
  },
  contact_phone: {
    type: DataTypes.STRING(50), allowNull: true, defaultValue: null, comment: '联系电话'
  },
  reference: {
    type: DataTypes.STRING(500), allowNull: true, defaultValue: null, comment: '备注'
  },
  sign_name: {
    type: DataTypes.STRING(20), allowNull: true, comment: '短信签名'
  },
  sms_code: {
    type: DataTypes.STRING(50), allowNull: true, comment: '短信模板CODE'
  },
  appid: {
    type: DataTypes.STRING(50), allowNull: true, defaultValue: null, comment: '开发者ID'
  },
  appsecret: {
    type: DataTypes.STRING(50), allowNull: true, defaultValue: null, comment: '开发者密码'
  },
  mchid: {
    type: DataTypes.STRING(50), allowNull: true, defaultValue: null, comment: '直连商户号'
  },
  apiv3key: {
    type: DataTypes.STRING(120), allowNull: true, defaultValue: null, comment: 'APIV3密钥'
  },
  display_name: {
    type: DataTypes.STRING(50), allowNull: true, defaultValue: null, comment: '显示名称'
  },
  my_image: {
    type: DataTypes.STRING(100), allowNull: true, defaultValue: null, comment: '个人中心图片'
  },
  image1: {
    type: DataTypes.STRING(150), allowNull: true, defaultValue: null, comment: '图片1'
  },
  image2: {
    type: DataTypes.STRING(150), allowNull: true, defaultValue: null, comment: '图片2'
  },
  image3: {
    type: DataTypes.STRING(150), allowNull: true, defaultValue: null, comment: '图片3'
  },
  image4: {
    type: DataTypes.STRING(150), allowNull: true, defaultValue: null, comment: '图片4'
  },
  logo: {
    type: DataTypes.STRING(120), allowNull: true, defaultValue: null, comment: '酒店logo'
  },
  created_id: {
    type: DataTypes.UUID, allowNull: false, validate: { isUUID: 4 }, comment: '创建用户', editable: false
  },
  updated_id: {
    type: DataTypes.UUID, allowNull: false, validate: { isUUID: 4 }, comment: '更新用户', model: 'Users', column: 'login_name'
  },
  created_at: {
    type: DataTypes.DATE, allowNull: false, comment: '创建时间', editable: false
  },
  updated_at: {
    type: DataTypes.DATE, allowNull: false, comment: '更新时间'
  },
  version: {
    type: DataTypes.INTEGER, allowNull: false, defaultValue: 0, comment: '版本控制'
  }
}, {
  sequelize: getSequelize(),
  tableName: 'hotels',
  comment: '主体信息表'
});

// https://sequelize.org/api/v6/class/src/model.js~model#static-method-hasMany
Hotels.associate = (db) => {
  Hotels.hasMany(db.UserHotels, {
    foreignKey: 'hotel_id',
    sourceKey: 'id',
    constraints: false,
    as: 'user_hotel'
  });

  Hotels.belongsTo(db.States, {
    foreignKey: 'state_id',
    targetKey: 'id',
    constraints: false,
    as: 'state'
  });
};

Hotels.beforeDestroy(async (instance, options) => {
  const { transaction } = options;
  const { models } = getSequelize();
  const {
    AppParameterValues,
    GuestFeatures,
    GuestTitles,
    MemberCardLogs,
    MemberCards,
    MemberLevels,
    MemberTypes,
    NameFeatures,
    Names,
    Outlets,
    Salers,
    TransactionCodes,
    TransactionDetails,
    UserHotels,
    UserPermissions,
    Users,
    Vips
  } = models;

  const results = await Promise.all([
    AppParameterValues.findOne({ where: { hotel_id: instance.id }, transaction }),
    GuestFeatures.findOne({ where: { hotel_id: instance.id }, transaction }),
    GuestTitles.findOne({ where: { hotel_id: instance.id }, transaction }),
    MemberCardLogs.findOne({ where: { hotel_id: instance.id }, transaction }),
    MemberCards.findOne({ where: { hotel_id: instance.id }, transaction }),
    MemberLevels.findOne({ where: { hotel_id: instance.id }, transaction }),
    MemberTypes.findOne({ where: { hotel_id: instance.id }, transaction }),
    NameFeatures.findOne({ where: { hotel_id: instance.id }, transaction }),
    Names.findOne({ where: { hotel_id: instance.id }, transaction }),
    Outlets.findOne({ where: { hotel_id: instance.id }, transaction }),
    Salers.findOne({ where: { hotel_id: instance.id }, transaction }),
    TransactionCodes.findOne({ where: { hotel_id: instance.id }, transaction }),
    TransactionDetails.findOne({ where: { hotel_id: instance.id }, transaction }),
    UserHotels.findOne({ where: { hotel_id: instance.id }, transaction }),
    UserPermissions.findOne({ where: { hotel_id: instance.id }, transaction }),
    Users.findOne({ where: { last_hotel_id: instance.id }, transaction }),
    Vips.findOne({ where: { hotel_id: instance.id }, transaction })
  ]);

  if (compact(results).length > 0) {
    throw new Error('无法删除酒店');
  }
});

export default Hotels;
